package fischl.huyaApi;

import com.google.gson.reflect.TypeToken;
import fischl.*;
import fischl.douyuApi.model.Danmu;
import fischl.log.Log;
import fischl.log.LogFactory;
import fischl.model.Room;
import fischl.model.VideoModel;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.Util;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.*;

public class HuyaWatcher extends Platform {
  private static final Log log = LogFactory.get("watcher");

  private List<VideoModel> videos = new ArrayList<>();

  public void doWatch() {
    List<VideoModel> result = new ArrayList<>();

    List<Room> rooms = RoomLoader.load();
    for (Room room : rooms) {
      List<VideoModel> videos = retrieveVideo(room);
      result.addAll(videos);
    }

    Set<String> ids = VideoMarker.getAllMarkedIds();
    result.stream()
      .sorted((o1, o2) -> o2.date.compareTo(o1.date))
      .limit(40)
      .forEach(v -> {
        v.isProcessed = ids.contains(v.vid);
        videos.add(v);
      });
  }

  private List<VideoModel> retrieveVideo(Room room) {
    Response response = null;
    Document doc;
    try {
      Request request = new Request.Builder().get().url(room.playback).build();
      response = Global.okHttpClient().newCall(request).execute();
      if (!response.isSuccessful() || response.body() == null) return Collections.emptyList();
      doc = Jsoup.parse(response.body().byteStream(), "UTF-8", "");
    } catch (Exception e) {
      log.e("error while retrieve video for " + room, e);
      return Collections.emptyList();
    } finally {
      Util.closeQuietly(response);
    }

    Elements videoInDates = doc.getElementsByClass("content-section");

    List<VideoModel> result = new ArrayList<>();
    for (int i = 0; i < videoInDates.size() && i < 2; i++) {
      Element item = videoInDates.get(i);
      Elements elements = item.select("div.section-list ul li");
      for (Element li : elements) {
        if (!li.attr("data-source-client-type").equals("1")) continue;
        VideoModel v = new VideoModel();
        try {
          String attr = li.getElementsByTag("a").first().attr("href");
          v.vid = attr.substring(6, attr.lastIndexOf('.'));
          v.videoUrl = "https://v.huya.com" + attr;
          v.dateStr = li.getElementsByClass("detail-right").first().text().trim();
          v.date = new SimpleDateFormat("yyyy-MM-dd").parse(v.dateStr);
        } catch (Exception e) {
          log.w("Error parsing vid: {}", li);
        }
        v.title = "[" + v.dateStr + "]" + v.vid + "-" + room.name;
        v.cover = li.getElementsByTag("img").first().attr("src");
        v.upId = room.upId + "";
        v.upName = room.name;
        v.liveRoom = room.liveRoom;
        v.publishTime = v.dateStr;
        v.sliceCount = 1;
        v.isProcessed = false;
        result.add(v);
      }
    }
    return result;
  }

  public List<VideoModel> getSnapshot() {
    return videos;
  }

  public VideoModel getVideoModelByVid(String vid) {
    List<VideoModel> snapshot = getSnapshot();
    for (VideoModel model : snapshot) {
      if (vid.equals(model.vid)) {
        return model;
      }
    }
    return null;
  }

  @Override
  public List<Danmu> getDanmu(String vid) {
    long[] time = VideoTimeUtil.getTime(vid);
    if(time== null) return Collections.emptyList();
    VideoModel model = getVideoModelByVid(vid);
    if(model == null) {
      log.e("Unable to find corresponding videoModel");
      return Collections.emptyList();
    }
    log.i("danmu args: cid={}, st={}, et={}", model.upId, time[0], time[1]);
    String url = String.format("%s/api/getDanmuByCid?cid=%s&startTime=%d&endTime=%d",
      Config.huyaDanmuUrl, model.upId, time[0], time[1]);

    Request request = new Request.Builder().get().url(url).build();
    try {
      Response response = Global.okHttpClient().newCall(request).execute();
      if(!response.isSuccessful() || response.body() == null) return Collections.emptyList();
      String json = response.body().string();
      Type type = TypeToken.getParameterized(List.class, Danmu.class).getType();
      return Global.gson().fromJson(json, type);
    } catch (IOException e) {
      log.e(e);
    }
    return Collections.emptyList();
  }
}
